Marko Gargenta @MarkoGargenta Marakana.com
Entrepreneur, Author, Speaker
Android™ Overview course is designed to give you a high level overview of the entire Android platform. It is our gentle introduction to what Android operating system is, how we got here, what makes it fundamentally different than any other platform, and how to take advantage of its uniqueness. Android Overview is designed for both technical managers seeking high-level understanding of the platform as well as developers warming up for a deep dive into programming for Android. By the end of this course, you will have a complete understanding of the entire operating system, at a light level.
Topics in this course include:
History of Android module focuses on how we got here. The goal of the module is to give us an idea of design philosophy behind Android, and what it may say about the future of the platform. At this high level, we explore both technical and business choices that effect the platform for a long time.
Topics in this module include:
Our goal is not just a single device. Our vision is a mobile platform that runs on many many different devices. – Eric Schmidt
2005 |
Google buys Android, Inc. |
2007 |
Google announces Open Handset Alliance |
2008 |
HTC Dev 1 announced, SDK 0.9 released |
2010 |
Android becomes #1 OS for smart phones |
2011 |
The battle for tablets start |
2012 |
TVs are the next frontier |
Beyond? |
Home automation, smart cars, wearable computing |
| Android version | API level | Codename |
|---|---|---|
Android 1.0 |
1 |
|
Android 1.1 |
2 |
|
Android 1.5 |
3 |
Cupcake |
Android 1.6 |
4 |
Donut |
Android 2.0 |
5 |
Eclair |
Android 2.01 |
6 |
Eclair |
Android 2.1 |
7 |
Eclair |
Android 2.2 |
8 |
Froyo (frozen yogurt) |
Android 2.3 |
9 |
Gingerbread |
Android 2.3.3 |
10 |
Gingerbread |
Android 3.0 |
11 |
Honeycomb |
Android 3.1 |
12 |
Honeycomb |
Android 3.2 |
13 |
Honeycomb |
Android 4.0 |
14 |
Ice Cream Sandwich |
Android 4.0.3 |
15 |
Ice Cream Sandwich |
Android 4.1 |
16 |
Jelly Bean |
Devices that have “With Google” add-on feature a set of Google’s proprietary applications, such as Google Play (aka Android Market), Google Maps, Gmail, Gtalk, and many others.
OEMs and carriers typically enter into a licensing agreement with Google in order to distribute Google version of Android.
Android Compatibility Test Suite: Defines “Android Compatible” Prevents incompatible releases Provides self testing
Fragmentations lines include:
Best practices in app development eliminate these issues. CTS ensures compliance.
What year did Google acquire Android, Inc.?
What is the vision for Android?
What does API Level stand for?
What is the most current API level?
How do you find out the differences between various Android APIs?
The goal of this module was to introduce you to how we got here.
By now, you should know about:
The Android technology stack can be divided into four layers. This module provides an overview of each layer and the role it plays in the Android platform.
Topics in this module include:
Mobile platform that runs on many different devices needs to be friendly for the entire ecosystem.
That includes:
Open source implies availability of source code, not the right to reuse it or modify it.
Android is based on a modified Linux kernel, which provides features such as:
The Android native layer contains:
|
|
Android exposes only a small subset of native libraries to application developers through Android’s Native Development Kit (NDK). |
Android applications execute in a Dalvik virtual machine (VM).
Android supports Java as the primary application development language.
The application framework layer implements Android’s Java language API for application development. It includes:
The application layer consists of pre-installed system applications and user-installed applications.
You distribute an Android application as a single file, known as an application package or APK, containing:
APKs must be signed with a security certificate before they can be installed on a device.
|
|
Google recommends a validity period of at least 25 years. |
User-installed applications can provide the same functionality as most system applications.
What are the major levels of the Android stack?
How is Android different than Ubuntu?
What is the license for Linux kernel?
How is Android Linux kernel different than mainline kernel?
What are some of the components that go into the native layer?
What is Dalvik and how is it different than JVM?
What are the components of the Android framework?
What does API level specify in the context of the stack?
What is the difference between system and user apps?
The goal of this module was to provide high level overview of the entire Android OS.
By now, you should be able to explain significance and purpose of:
The goal of this module is to have you write a simple Hello, World application. By the end of this module, you should be able to identify main parts of an app. You should also be able to verify that your tools are setup properly and that you can run the application on an Android device, either physical or emulated. Topics covered include:
Android SDK is all you need. Get it from d.android.com[http://developer.android.com/sdk/index.html] It is supported for Mac, Linux, or Windows. About equally.
You also need JDK.
And most people tend to use Eclipse[http://eclipse.org], a powerful and feature-rich tool.
Use the Eclipse tool to create a new Android project.
Here are some key constructs:
Project |
Eclipse construct |
Target |
minimum to run |
App name |
whatever |
Package |
Java package |
Activity |
Java class |
Java Code + XML and Other Resources + Manifest File = Android App
Android is agnostic to emulator versus a real device. For the most part.
Emulator is not a simulator!
Lately, for serious development, you may want to have a real device.
Where do you get the SDK from?
Once you download it and install the initial SDK, what next?
What are some of the main tools in the SDK?
What does ADT stand for, and where do you get it from?
What are three main parts of an app?
What is an Android APK?
What is the difference between an emulator and a simulator?
How do you run your app on a real device?
The goal of this module was to create a simple Android app, to dissect it and analyze various parts that make up an app, and to build and run it on an Android device.
The goal of this module is to introduce you to main components used to create Android apps. By the end of this module, you should have a good idea what Android app building blocks are, and their key properties.
Seven iterations of an app:
The objective of this module is to explain how to go about designing a typical Android app. You will have a chance to see an example app, Yamba, using most of the standard Android building blocks. By the end of this talk, you should have high-level understanding about designing an Android app.
D/ActivityDemo( 6708): onCreate D/ActivityDemo( 6708): onStart D/ActivityDemo( 6708): onResume
... D/ActivityDemo( 6708): onClickAnotherActivity D/ActivityDemo( 6708): onPause D/ActivityDemo( 6708): onStop D/ActivityDemo( 6708): onRestart D/ActivityDemo( 6708): onStart D/ActivityDemo( 6708): onResume
... D/ActivityDemo( 6708): onPause D/ActivityDemo( 6708): onStop D/ActivityDemo( 6708): onDestroy D/ActivityDemo( 6708): onCreate D/ActivityDemo( 6708): onStart D/ActivityDemo( 6708): onResume
... D/ActivityDemo( 6708): onPause D/ActivityDemo( 6708): onStop
... D/ActivityDemo( 6708): onRestart D/ActivityDemo( 6708): onStart D/ActivityDemo( 6708): onResume
package com.marakana.android.lifecycle; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class ActivityDemo extends Activity { static final String TAG = "ActivityDemo"; // --- Lifecycle methods @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Log.d(TAG, "onCreate"); } @Override protected void onStart() { super.onStart(); Log.d(TAG, "onStart"); } @Override protected void onResume() { super.onResume(); Log.d(TAG, "onResume"); } @Override protected void onPause() { super.onPause(); Log.d(TAG, "onPause"); } @Override protected void onStop() { super.onStop(); Log.d(TAG, "onStop"); } @Override protected void onRestart() { super.onRestart(); Log.d(TAG, "onRestart"); } @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); } // --- Options menu methods @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.item_start_service: startService(new Intent(this, ServiceDemo.class)); return true; case R.id.item_stop_service: stopService(new Intent(this, ServiceDemo.class)); return true; case R.id.item_refresh: startService(new Intent("marakana.intent.action.IntentServiceDemo")); return true; case R.id.item_send_broadcast: sendBroadcast(new Intent("marakana.intent.action.ReceiverDemo")); return true; case R.id.item_location: startActivity(new Intent(this, SystemServicesDemo.class)); return true; case R.id.item_insert: getContentResolver() .insert(ProviderDemo.CONTENT_URI, new ContentValues()); return true; case R.id.item_query: getContentResolver().query(ProviderDemo.CONTENT_URI, null, null, null, null); return true; } return false; } // --- Button click event handler public void onClickAnotherActivity(View v) { startActivity(new Intent(this, AnotherActivity.class)); Log.d(TAG, "onClickAnotherActivity"); } }
Used to setup your activity. You will almost always have to have it. Good place to inflate the UI and setup listeners.
Use them to turn on and off things that you’d like to have running only while the activity is visible. This is important for things that consume a lot of battery, such as GPS and sensors.
Use to setup code that starts/stops the activity. Unlike onResume() and onPause(), it includes Paused state as well.
Called when the activity is restarted. It is followed by onStart() and onResume().
A good place to do any cleanup before the activity is cleaned up from memory. This is the counter-part to onCreate().
Use them to setup your menu. onOptionsItemSelected() loads the menu, typically from an XML resource. onOptionsItemSelected() is called whenever an option menu item is clicked on.
Used to handle the UI events.
Register the activity in the Android Manifest file:
... <activity android:name=".ActivityDemo" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ...
The intent filter specifies that this activity is to be the main entry point into the application as well as that it should be shown in the app launcher on home screen.
... <activity android:name=".AnotherActivity"></activity> ...
There are two approaches to building Android UI:
The best is to use both:
Star with declaring the look and feel using XML
Inflate XML into Java
Finish by programming the actions using Java
Starts an activity specified by the intent. If activity does not exist already, it calls onCreate() to create it. Otherwise, it calls onStart() and onResum().
Starts a service. Even if the service is not created yet, it called onCreate() on the service first.
Stops a service that is already running. If service is not running, it does nothing.
Binds to a service. Requires that the service returns a binder via onBind() method.
Sends a broadcast. If there’s a broadcast receiver registered to filter for the same action as this intent is specifying, that receiver’s onReceive() method will be called.
... startActivity(new Intent(this, AnotherActivity.class)); ... startService(new Intent(this, ServiceDemo.class)); ...
this is the context from which this intent is being sent, in our case an Activity.
... startService(new Intent("marakana.intent.action.IntentServiceDemo")); ... sendBroadcast(new Intent("marakana.intent.action.ReceiverDemo")); ...
Requires that there’s an intent filter filtering for this particular intent, for example:
... <service android:name=".IntentServiceDemo"> <intent-filter> <action android:name="marakana.intent.action.IntentServiceDemo" /> </intent-filter> </service> ... <receiver android:name=".ReceiverDemo"> <intent-filter> <action android:name="marakana.intent.action.ReceiverDemo" /> </intent-filter> </receiver> ...
Intent filter is a way for us to assign certain action to an activity, service, receiver or similar.
Action is one of system defined actions, or something you come up with.
Intent filter typically goes into Android Manifest file, within <activity>, <service>, or <receiver> elements.
... <intent-filter> <action android:name="some.action.goes.here" /> </intent-filter> ...
The action bar, introduced in Honeycomb (API 11) is a title bar that includes:
Android automatically displays an action bar on an API 11+ system if the <uses-sdk> element of your applications manifest:
Either or these settings enable the "holographic look and feel" introduced in Honeycomb, which includes action bar support.
With the action bar enabled, legacy option menu items appear automatically in the action bar’s overflow menu. You reveal the overflow menu with:
To display an option menu item as an action item, in the menu resource file add android:showAsAction="ifRoom" to the <item> element.
If your menu item supplies both a title and an icon, the action item shows only the icon by default.
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_save" android:icon="@drawable/ic_menu_save" android:title="@string/menu_save" android:showAsAction="ifRoom|withText" /> </menu>
|
|
The withText value is a hint to the action bar. The action bar will show the title if possible, but might not if an icon is available and the action bar is constrained for space. |
API 14 introduced split action bar support.
You enable split action bar in the manifest add uiOptions="splitActionBarWhenNarrow":
|
|
Devices on API 13 or earlier ignore the uiOptions attribute. |
You can enable the application icon — which appears in the action bar on the left side — to behave as an action item. If enabled, your app should respond by:
When the user taps the app icon, the system calls your activity’s onOptionsItemSelected() method. The MenuItem passed as an argument has an ID of android.R.id.home.
|
|
The app icon was enabled by default in APIs 11-13. API 14 disables it be default. To enable it in API 14 or later: if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) { getActionBar().setHomeButtonEnabled(true); } |
D/ServiceDemo( 7623): onCreate D/ServiceDemo( 7623): onStartCommand
... D/ServiceDemo( 7623): onStartCommand
... D/ServiceDemo( 7623): onDestroy
D/IntentServiceDemo( 7748): onCreate D/IntentServiceDemo( 7748): onHandleIntent for action: marakana.intent.action.IntentServiceDemo D/IntentServiceDemo( 7748): onDestroy
package com.marakana.android.lifecycle; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class ServiceDemo extends Service { static final String TAG = "ServiceDemo"; @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onCreate() { Log.d(TAG, "onCreate"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand"); return START_STICKY; } @Override public void onDestroy() { Log.d(TAG, "onDestroy"); } }
package com.marakana.android.lifecycle; import android.app.IntentService; import android.content.Intent; import android.util.Log; public class IntentServiceDemo extends IntentService { static final String TAG = "IntentServiceDemo"; public IntentServiceDemo() { super(TAG); } @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate"); } @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent for action: " + intent.getAction()); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); } }
Required, but for unbound services, we just return null.
Called when service is first created.
Called is called every time service is started.
Called when service is stopped. It is subsequently destroyed.
It needs to pass the name of this service to its super.
Called when service is first created.
This is where the work of the service runs.
Called when service is stopped. It is subsequently destroyed.
... <service android:name=".ServiceDemo"></service> ...
... <service android:name=".IntentServiceDemo"> <intent-filter> <action android:name="marakana.intent.action.IntentServiceDemo" /> </intent-filter> </service> ...
package com.marakana.android.lifecycle; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.util.Log; import android.provider.Settings.System; public class ProviderDemo extends ContentProvider { static final String TAG = "ProviderDemo"; static final String AUTHORITY = "content://com.marakana.android.lifecycle.providerdemo"; public static final Uri CONTENT_URI = Uri.parse(AUTHORITY); static final String SINGLE_RECORD_MIME_TYPE = "vnd.android.cursor.item/vnd.marakana.android.lifecycle.status"; static final String MULTIPLE_RECORDS_MIME_TYPE = "vnd.android.cursor.dir/vnd.marakana.android.lifecycle.status"; @Override public boolean onCreate() { Log.d(TAG, "onCreate"); return true; } @Override public String getType(Uri uri) { String ret = getContext().getContentResolver().getType(System.CONTENT_URI); Log.d(TAG, "getType returning: " + ret); return ret; } @Override public Uri insert(Uri uri, ContentValues values) { Log.d(TAG, "insert uri: " + uri.toString()); return null; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { Log.d(TAG, "update uri: " + uri.toString()); return 0; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { Log.d(TAG, "delete uri: " + uri.toString()); return 0; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Log.d(TAG, "query with uri: " + uri.toString()); return null; } }
Used to initialize this content provider. This method runs on UI thread, so should be quick. Good place to instantiate database helper, if using database.
Returns the mime time for the given uri. Typically, this MIME type will either be something like vnd.android.cursor.item/vnd.marakana.android.lifecycle.status for a single item or vnd.android.cursor.dir/vnd.marakana.android.lifecycle.status for multiple items.
Inserts the values into the provider returning uri that points to the newly inserted record.
Updates records(s) specified by either the uri or selection/selectionArgs combo. Returns number of records affected.
Deletes records(s) specified by either the uri or selection/selectionArgs combo. Returns number of records affected.
Queries the provider for the record(s) specified by either uri or`selection`/selectionArgs/grouping/having combo.
... <provider android:name=".ProviderDemo" android:authorities="com.marakana.android.lifecycle.providerdemo" /> ...
The authority of this provider must match the uri authority that this provider is responding to.
Adapters connect potentially large data sets to small views
A fragment is a class implementing a portion of an activity.
Loaders make it easy to load data asynchronously in an activity or fragment. Loaders have these characteristics:
Loaders were introduced in Honeycomb (API 11).
An application that uses loaders typically includes the following:
Fragments were added to the Android API in Honeycomb, API 11.
The primary classes related to fragments are:
The base class for all fragment definitions
The class for interacting with fragment objects inside an activity
The class for performing an atomic set of fragment operations
Google provides the Compatibility Package, a Java library that you can include in an application, implementing support for fragments and other Honeycomb features (loaders).
package com.marakana.android.lifecycle; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class ReceiverDemo extends BroadcastReceiver { static final String TAG = "ReceiverDemo"; @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "onReceive action: "+intent.getAction() ); } }
D/ReceiverDemo( 7964): onReceive action: marakana.intent.action.ReceiverDemo
This is the only method you typically care about for a broadcast receiver. It is called when this receiver is invoked.
<receiver android:name=".ReceiverDemo"> <intent-filter> <action android:name="marakana.intent.action.ReceiverDemo" /> </intent-filter> </receiver>
... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // Create the receiver receiver = new TimelineReceiver(); filter = new IntentFilter( UpdaterService.NEW_STATUS_INTENT ); } protected void onResume() { super.onResume(); super.registerReceiver(receiver, filter, "com.marakana.yamba.SEND_TIMELINE_NOTIFICATIONS", null); } @Override protected void onPause() { super.onPause(); unregisterReceiver(receiver); } ...
Widgets are essentially Broadcast Receivers
<receiver android:name=".YambaWidget" android:label="@string/app_name" > <intent-filter> <action android:name="com.marakana.broadcast.NEW_STATUS" /> </intent-filter> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget" /> </receiver>
Meta data specifies the default size of the widget, plus the update period.
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minHeight="72dp" android:minWidth="294dp" android:updatePeriodMillis="10000" > </appwidget-provider>
package com.marakana.android.yamba; ... public class YambaWidget extends AppWidgetProvider { private static final String TAG = YambaWidget.class.getSimpleName(); @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); if (intent.getAction().equals(YambaApp.NEW_STATUS_BROADCAST)) { AppWidgetManager appWidgetManager = AppWidgetManager .getInstance(context); this.onUpdate(context, appWidgetManager, appWidgetManager .getAppWidgetIds(new ComponentName(context, YambaWidget.class))); Log.d(TAG, "onReceived"); } } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); // Get the data Cursor cursor = context.getContentResolver().query( StatusProvider.CONTENT_URI, null, null, null, StatusData.SORT_BY); // Do we have any data? if (cursor!=null && cursor.moveToFirst()) { String user = cursor.getString(cursor .getColumnIndex(StatusData.C_USER)); String text = cursor.getString(cursor .getColumnIndex(StatusData.C_TEXT)); // Loop thru all the widget instances for (int appWidgetId : appWidgetIds) { RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.row); views.setTextViewText(R.id.text_user, user); views.setTextViewText(R.id.text_text, text); views.setTextViewText(R.id.text_createdAt, ""); appWidgetManager.updateAppWidget(appWidgetId, views); } } Log.d(TAG, "onUpdated"); } }
Name four main Android app building blocks.
What is an activity?
Name major callback methods of an activity.
What is a service?
Name major callback methods of a service.
What is a broadcast receiver?
Name major callback methods of a broadcast receiver.
What is a content provider?
Name major callback methods of a content provider.
What does an Android app consist of?
This module was an introduction to main components that make up an app. By now, you should know of activities, services, providers and receivers as well as intents and other major components of an app.
This module provides an overview of some of the tools available in Android SDK that can help you with debugging your apps. By the end of this module you should have a general knowledge of what is available and how to use it.
The tools we’ll explore include:
The universal, most versatile way to track what is going on in your app.
Can be viewed via command line or Eclipse.
Logs can be generated both from SDK Java code, or low-level C code via Bionic libc extension.
Your standard debugger is included in SDK, with all the usual bells & whistles.
Traceview helps you profile you application and find bottlenecks. It shows execution of various calls through the entire stack. You can zoom into specific calls.
Hierarchy Viewer helps you analyze your User Interface.
Base UI tends to be the most “expensive” part of your application, this tool is very useful.
What is the global logging framework in Android?
What criteria can you filter the logs for?
How do you debug Android apps?
What is the tool for profiling the execution of your code?
How do you profile your UI?
In this module, you learned about some of the SDK tools, such as Logcat, Debugger, Traceview, and HierarchyViewer. You should be able to identify which one to use in what situation.
The goal of this module is to provide high level overview of how Android security is architected. By the end of this module, you should know how apps are sandboxed and how kernel enforces security rights. Topics covered include:
No app can adversely impact other apps, user, or OS
Each application is its own sandbox:
Linux manages security:
An application is an island on its own.
It contains any number of Activities, Services, Receivers and Providers.
It has its own file system, database, place to store native libraries.
No other app can access any of its data without prior permission.
A component that does something potentially dangerous can require callers to have permission to access it.
App that wants to use it must have user grant it permission.
Permissions are granted at install time. All or nothing. Forever.
What is the main premise of Android security?
Who enforces the sandboxing?
What if apps what to connect to one another?
What are the permission levels?
This module was a high level overview of how security in Android works. You show know that Linux kernel is the sole enforcer of the security rights, and that each app in Android runs in its own process.
The goal of this module was to introduce you to Android platform. By now, you should know a bit about:
/
#